//
//  IPAPurchase.m
//  ApplePurchaseTest
//
//  Created by 赵隆杰 on 2024/9/23.
//

#import "IPAPurchase.h"
#import <StoreKit/StoreKit.h>
#import "CQLoading.h"
#import "CQToast.h"
#import "YZYSaccountStore.h"
#import "SandBoxHelper.h"
#import "ZCNetworkManager.h"
#import "YZYSDKManagerHeader.h"

static NSString *const receiptKey = @"receiptKey";

dispatch_queue_t iap_queue(){
    static dispatch_queue_t as_iap_queue;
    static dispatch_once_t onceToken_iap_queue;
    dispatch_once(&onceToken_iap_queue, ^{
        as_iap_queue = dispatch_queue_create("com.iap.queue", DISPATCH_QUEUE_CONCURRENT);
    });
    return as_iap_queue;
}

@interface IPAPurchase()
<SKPaymentQueueDelegate, SKProductsRequestDelegate, SKPaymentTransactionObserver>
/**
 *
 */
@property (nonatomic, strong) SKProductsRequest * request;

/**
 *购买凭证(存储base64编码的交易凭证)
 */
@property (nonatomic, copy) NSString * receipt;
/**
 *
 */
@property (nonatomic, copy) NSString * productId;

//订单请求是是否从通知过来，这个时候不需要toast
@property (nonatomic, assign) BOOL isFromStartManager;

@end

static IPAPurchase *manager = nil;

@implementation IPAPurchase

+(instancetype)manager{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if(!manager){
            manager = [[IPAPurchase alloc] init];
        }
    });
    return manager;
}
#pragma mark -- 漏单处理
-(void)startManager{
    self.isFromStartManager = YES;
    dispatch_sync(iap_queue(), ^{
        [[SKPaymentQueue defaultQueue] addTransactionObserver:manager];
    });
}
#pragma mark -- 移除交易事件
-(void)stopManager{
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
    });
}
#pragma mark -- 发起购买的方法
-(void)buyProductWithProductID:(NSString *)productID payResult:(PayResult)payResult{
    self.payResultBlock = payResult;
    [self removeAllUncompleteTransactionBeforeStartNewtransaction];
    //购买中HUD。。。
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [CQLoading showWithInfo:@" 购买中... "];
        });
    });
    
    self.productId = productID;
    if (!self.productId.length) {
        [self dismissCustom];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"没有对应的商品" preferredStyle:UIAlertControllerStyleAlert];
                //添加取消按钮
                UIAlertAction* cancelBtn = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
                }];
                [alert addAction:cancelBtn];
                //显示
                [[YZYSaccountStore sharedInstance] getCurrentWindowWithCompletion:^(UIWindow *window) {
                    if (window) {
                        UIViewController *curViewController = window.rootViewController;
                        [curViewController presentViewController:alert animated:YES completion:nil];
                    }
                }];
            });
        });
    }
    
    if ([SKPaymentQueue canMakePayments]) {
        [self requestProductInfo:self.productId];
    } else {
        [self dismissCustom];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:@"请先开启应用内付费购买功能。" preferredStyle:UIAlertControllerStyleAlert];
                //添加取消按钮
                UIAlertAction* cancelBtn = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) {
                }];
                [alert addAction:cancelBtn];
                //显示
                [[YZYSaccountStore sharedInstance] getCurrentWindowWithCompletion:^(UIWindow *window) {
                    if (window) {
                        UIViewController *curViewController = window.rootViewController;
                        [curViewController presentViewController:alert animated:YES completion:nil];
                    }
                }];
            });
        });
    }
}
#pragma mark -- 结束上次未完成的交易 防止串单
-(void)removeAllUncompleteTransactionBeforeStartNewtransaction{
    self.isFromStartManager = NO;
    NSArray *transactionsArray = [SKPaymentQueue defaultQueue].transactions;
    if(transactionsArray.count >0){
        //检测是否有未完成的交易
        SKPaymentTransaction *transaction = [transactionsArray firstObject];
        if(transaction.transactionState == SKPaymentTransactionStatePurchased){
            [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
            return;
        }
    }
}
#pragma mark --发起购买请求
-(void)requestProductInfo:(NSString *)productId{
    NSArray *productArray = [[NSArray alloc] initWithObjects:productId, nil];
    NSSet *IDSet = [NSSet setWithArray:productArray];
    self.request = [[SKProductsRequest alloc] initWithProductIdentifiers:IDSet];
    self.request.delegate = self;
    [self.request start];
}

#pragma mark -- SKProductsRequestDelegate 查询成功后的回调
-(void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response{
    
    NSArray *myProduct = response.products;
    if(myProduct.count == 0){
        //没有该商品信息HUD。。。
        [self dismissCustom];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                [CQToast showWithMessage:@"无法获取产品信息,购买失败"];
            });
        });
        
        if (self.payResultBlock) {
            self.payResultBlock(NO, nil, @"无法获取产品信息,购买失败");
        }
        return;
    }
    
    SKProduct *product = nil;
    for (SKProduct *pro in myProduct) {
        NSLog(@"yzysdk - SKProduct 描述信息%@", [pro description]);
        NSLog(@"yzysdk - 产品标题 %@" , pro.localizedTitle);
        NSLog(@"yzysdk - 产品描述信息: %@" , pro.localizedDescription);
        NSLog(@"yzysdk - 价格: %@" , pro.price);
        NSLog(@"yzysdk - Product id: %@" , pro.productIdentifier);
        
        if([pro.productIdentifier isEqualToString:self.productId]){
            product = pro;
            break;
        }
    }
    
    if(product){
        SKMutablePayment *payment = [SKMutablePayment paymentWithProduct:product];
        payment.applicationUsername = self.orderNumber;
        [[SKPaymentQueue defaultQueue] addPayment:payment];
    }
    else{
         NSLog(@"yzysdk - 没有此商品");
        [self dismissCustom];
    }
}
//查询失败后的回调
-(void)request:(SKRequest *)request didFailWithError:(NSError *)error{
    [self dismissCustom];
    if (self.payResultBlock) {
        self.payResultBlock(NO, nil, [error localizedDescription]);
    }
}
////如果没有设置监听购买结果将直接跳至反馈结束
-(void)requestDidFinish:(SKRequest *)request{
    [self dismissCustom];
}
#pragma mark -- 监听结果
-(void)paymentQueue:(SKPaymentQueue *)queue updatedTransactions:(NSArray<SKPaymentTransaction *> *)transactions{
    
    //当用户购买的操作有结果时，就会触发下面的回调函数，
    for (SKPaymentTransaction * transaction in transactions) {
        
        switch (transaction.transactionState) {
            case SKPaymentTransactionStatePurchased:{
                [self completeTransaction:transaction];
//                [self dismissCustom];
            }break;

            case SKPaymentTransactionStateFailed:{
                [self failedTransaction:transaction];
                [self dismissCustom];
            }break;

            case SKPaymentTransactionStateRestored:{//已经购买过该商品
                [self restoreTransaction:transaction];
                [self dismissCustom];
            }break;

            case SKPaymentTransactionStatePurchasing:{
                NSLog(@"yzysdk - 正在购买中...");
            }break;

            case SKPaymentTransactionStateDeferred:{
                NSLog(@"yzysdk - 交易延迟");
                [self failedTransaction:transaction];
                [self dismissCustom];
            }break;

            default:
                break;
          }
    }
}
//完成交易
#pragma mark -- 交易完成的回调
- (void)completeTransaction:(SKPaymentTransaction *)transaction{
    NSLog(@"yzysdk - 购买成功,准备验证发货");
    [self getReceipt]; //获取交易成功后的购买凭证
    [self saveReceipt:transaction]; //存储交易凭证
    [self checkIAPFiles:transaction];
}

#pragma mark -- 处理交易失败回调
- (void)failedTransaction:(SKPaymentTransaction *)transaction
{
    NSString *error = nil;
    if(transaction.error.code != SKErrorPaymentCancelled) {
        //购买失败HUD。。。
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                [CQToast showWithMessage:@"购买失败"];
            });
        });
    } else {
        //取消购买HUD。。。
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                [CQToast showWithMessage:@"取消购买"];
            });
        });
    }

    if (self.payResultBlock) {
        self.payResultBlock(NO, nil, error);
    }
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

- (void)restoreTransaction:(SKPaymentTransaction *)transaction{
    [[SKPaymentQueue defaultQueue] finishTransaction:transaction];
}

#pragma mark -- 获取购买凭证
-(void)getReceipt{
    NSURL * receiptUrl = [[NSBundle mainBundle] appStoreReceiptURL];
    NSData * receiptData = [NSData dataWithContentsOfURL:receiptUrl];
    NSString * base64String = [receiptData base64EncodedStringWithOptions:NSDataBase64EncodingEndLineWithLineFeed];
    self.receipt = base64String;
}

#pragma mark -- 存储购买凭证
-(void)saveReceipt:(SKPaymentTransaction *)transaction{
    NSString * userId;
    NSString * order;

    if (self.userid) {
        userId = self.userid;
        [[NSUserDefaults standardUserDefaults]setObject:userId forKey:@"unlock_iap_userId"];
    }else{

        userId = [[NSUserDefaults standardUserDefaults]objectForKey:@"unlock_iap_userId"];
    }

    order = transaction.payment.applicationUsername;
    
    if (order == nil) {
        //order为空表示之前未完成交易
        NSLog(@"yzysdk - order为空表示之前未完成交易");
        return;
    }

    NSString *fileName = [[UIDevice currentDevice].identifierForVendor UUIDString];
    NSString *savedPath = [NSString stringWithFormat:@"%@/%@.plist", [SandBoxHelper iapReceiptPath], fileName];
    NSMutableDictionary * dic = [[NSMutableDictionary alloc]init];
    [dic setObject:self.receipt forKey:receiptKey];
    [dic setObject: userId forKey:@"user_id"];
    [dic setObject: order forKey:@"order"];
    BOOL ifWriteSuccess  = [dic writeToFile:savedPath atomically:YES];

    if (ifWriteSuccess) {
        NSLog(@"yzysdk - 购买凭据存储成功!");
    }
}

#pragma mark -- 验证本地数据
-(void)checkIAPFiles:(SKPaymentTransaction *)transaction{

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error = nil;
    NSArray *cacheFileNameArray = [fileManager contentsOfDirectoryAtPath:[SandBoxHelper iapReceiptPath] error:&error];
    if (error == nil) {
        
        NSString *filePath = @"";
        for (NSString *name in cacheFileNameArray) {

            if ([name hasSuffix:@".plist"]){ //如果有plist后缀的文件，说明就是存储的购买凭证

                filePath = [NSString stringWithFormat:@"%@/%@", [SandBoxHelper iapReceiptPath], name];

                [self sendAppStoreRequestBuyPlist:filePath trans:transaction];
            }
        }
        if (filePath.length == 0) {
            [self dismissCustom];
        }

    } else {
        [self dismissCustom];
    }
}

#pragma mark -- 存储成功订单
-(void)SaveIapSuccessReceiptDataWithReceipt:(NSString *)receipt Order:(NSString *)order UserId:(NSString *)userId{
    NSMutableDictionary * mdic = [[NSMutableDictionary alloc]init];
    [mdic setObject:[self getCurrentZoneTime] forKey:@"time"];
    [mdic setObject: order forKey:@"order"];
    [mdic setObject: userId forKey:@"user_id"];
    [mdic setObject: receipt forKey:receiptKey];
    NSString *fileName = [[UIDevice currentDevice].identifierForVendor UUIDString];
    NSString * successReceiptPath = [NSString stringWithFormat:@"%@/%@.plist", [SandBoxHelper SuccessIapPath], fileName];
    //存储购买成功的凭证
    [mdic writeToFile:successReceiptPath atomically:YES];
}

#pragma mark -- 获取系统时间的方法
-(NSString *)getCurrentZoneTime{
    NSDate * date = [NSDate date];
    NSDateFormatter*formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSString*dateTime = [formatter stringFromDate:date];
    return dateTime;
}

#pragma mark -- 去服务器验证购买
-(void)sendAppStoreRequestBuyPlist:(NSString *)plistPath trans:(SKPaymentTransaction *)transaction {
    if (!self.isFromStartManager) {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            dispatch_async(dispatch_get_main_queue(), ^{
                [CQLoading showWithInfo:@" 验证中... "];
            });
        });
    }
    
    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
    NSString *order = [dic objectForKey:@"order"];
    if (order == nil) {
        NSLog(@"yzysdk - 获取不到有效订单");
        [self dismissCustom];
        if (self.payResultBlock) {
            self.payResultBlock(NO, nil, @"获取不到有效订单");
        }
        return;
    }

    [self sendAppStoreRequestBuyPlist1:plistPath trans:transaction count:0];
    
}

#pragma mark -- 发送信息去验证是否成功
-(void)sendAppStoreRequestBuyPlist1:(NSString *)plistPath trans:(SKPaymentTransaction *)transaction count:(int)count {
    
    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
    NSString * transactionIdentifier = transaction.transactionIdentifier;
    NSString * goodID = transaction.payment.productIdentifier;
    NSString * receipt = [dic objectForKey:receiptKey];
    NSString * order = [dic objectForKey:@"order"];
    NSString * userId = [dic objectForKey:@"user_id"];
    
    [self requestPayNotifyComplete:^(BOOL result, NSString *resultMsg, int requestCount) {
        if (result == YES) {
            NSLog(@"yzysdk - 服务器验证成功!");
            [self dismissCustom];
            
            [[NSUserDefaults standardUserDefaults]removeObjectForKey:@"unlock_iap_userId"];
            //这里将成功但存储起来
            [self SaveIapSuccessReceiptDataWithReceipt:receipt Order:order UserId:userId];

            [self successConsumptionOfGoodsWithOrder:order];
            
            [[SKPaymentQueue defaultQueue]finishTransaction:transaction];
            
            if (self.payResultBlock) {
                self.payResultBlock(YES, transactionIdentifier, nil);
            }
        } else {
            //一次验证失败需要再请求一次，第二次失败就不管了
            if (requestCount == 0) {
                dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                    [self sendAppStoreRequestBuyPlist1:plistPath trans:transaction count:1];
                });
                
            } else {
                [self dismissCustom];
                if (self.payResultBlock) {
                    self.payResultBlock(NO, nil, resultMsg);
                }
            }
        }
    } goodID:goodID order:order receipt:receipt count:count];
}

- (void)requestPayNotifyComplete:(void(^)(BOOL result, NSString *resultMsg, int requestCount))complete goodID:(NSString *)goodID order:(NSString *)order receipt:(NSString *)receipt count:(int)count {
    NSDictionary *params = @{
        @"productId": goodID,//商品id
        @"chooseEnv": @1,//是否是真实环境 1真实环境 0沙箱环境
        @"orderNo": order,//订单号
        @"receipt": receipt//苹果传递给客户端支付成功的值
    };
    [ZCNetworkManager postWithURL:YZY_AppendUrl(YZY_pay_notify) Params:params success:^(id responseObject) {
        NSDictionary *surperdic = (NSDictionary *)responseObject;
        
        NSString *code = [NSString stringWithFormat:@"%@",surperdic[@"code"]];
        NSString *msg = [NSString stringWithFormat:@"%@",surperdic[@"msg"]];
//        NSDictionary *resultDic = [NSDictionary dictionaryWithDictionary:surperdic[@"data"]];
        if ([code isEqualToString:@"200"]) {
            complete(YES, @"验证成功", count);
        } else {
            complete(NO, msg, count);
        }
        
    } failure:^(NSString *error) {
        complete(NO, error, count);
    }];
}

#pragma mark -- 根据订单号来移除本地凭证的方法
-(void)successConsumptionOfGoodsWithOrder:(NSString * )cpOrder{

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError * error;
    if ([fileManager fileExistsAtPath:[SandBoxHelper iapReceiptPath]]) {

        NSArray * cacheFileNameArray = [fileManager contentsOfDirectoryAtPath:[SandBoxHelper iapReceiptPath] error:&error];

        if (error == nil) {

            for (NSString * name in cacheFileNameArray) {

                NSString * filePath = [NSString stringWithFormat:@"%@/%@", [SandBoxHelper iapReceiptPath], name];

                [self removeReceiptWithPlistPath:filePath ByCpOrder:cpOrder];

            }
        }
    }
}

#pragma mark -- 根据订单号来删除 存储的凭证
-(void)removeReceiptWithPlistPath:(NSString *)plistPath   ByCpOrder:(NSString *)cpOrder{

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError * error;
    NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithContentsOfFile:plistPath];
    NSString * order = [dic objectForKey:@"order"];

    if ([cpOrder isEqualToString:order]) {
        //移除与用户id订单号一样的plist 文件
        BOOL ifRemove =  [fileManager removeItemAtPath:plistPath error:&error];
        if (ifRemove) {
            NSLog(@"yzysdk - 成功订单移除成功");
        }else{
            NSLog(@"yzysdk - 成功订单移除失败");
        }
    }else{
        NSLog(@"yzysdk - 本地无与之匹配的订单");
    }
}

- (void)dismissCustom {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{
            [CQLoading remove];
        });
    });
}
@end

